package com.gitee.core.ftp;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Iterator;
import java.util.Set;
import java.util.Vector;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.joda.time.DateTime;

import com.google.common.collect.Sets;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.ChannelSftp.LsEntry;
import com.jcraft.jsch.SftpException;

/**
 * sftp工具。注意：构造方法有两个：分别是基于密码认证、基于秘钥认证。
 * 
 */
public class SftpUtils {

    private ChannelSftp sftp;

    /**
     * 构造基于密码认证的sftp对象
     * 
     * @param userName
     * @param password
     * @param host
     * @param port
     */
    public SftpUtils(ChannelSftp sftp) {
        this.sftp = sftp;
    }

    /**
     * 
     * upload
     * 
     * @Description: 上传文件
     * @author Administrator
     * @date 2017年12月27日 下午5:33:58
     * @param directory
     * @param uploadFile
     * @return
     * 
     */
    public boolean upload(String directory, String uploadFile) {
        boolean success = false;
        FileInputStream fis = null;
        try {
            sftp.cd(directory);
        } catch (SftpException e) {
            System.err.println("directory is not exist");
            try {
                sftp.mkdir(directory);
                sftp.cd(directory);
            } catch (SftpException e1) {
                System.err.println(e.getMessage());
                return false;
            }
        }
        try {
            File file = new File(uploadFile);
            fis = new FileInputStream(file);
            sftp.put(fis, file.getName());
            success = true;
        } catch (Exception e) {
            System.err.println(e.getMessage());
        } finally {
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    System.err.println(e.getMessage());
                }
            }
        }
        return success;
    }

    /**
     * 
     * upload
     * 
     * @Description: 上传文件
     * @author Administrator
     * @date 2018年1月9日 下午5:50:11
     * @param pwd
     * @param directory
     * @param uploadFile
     * @return
     * 
     */
    public boolean upload(String pwd, String directory, String uploadFile) {
        boolean success = false;
        FileInputStream fis = null;
        try {
            sftp.cd(pwd);
            sftp.cd(directory);
        } catch (SftpException e) {
            System.err.println("directory is not exist");
            try {
                sftp.mkdir(directory);
                sftp.cd(directory);
            } catch (SftpException e1) {
                System.err.println(e.getMessage());
                return false;
            }
        }
        try {
            File file = new File(uploadFile);
            fis = new FileInputStream(file);
            sftp.put(fis, file.getName());
            success = true;
        } catch (Exception e) {
            System.err.println(e.getMessage());
        } finally {
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    System.err.println(e.getMessage());
                }
            }
        }
        return success;
    }

    /**
     * 下载文件
     * 
     * @param directory
     *            下载目录
     * @param downloadFile
     *            下载的文件
     * @param saveFile
     *            存在本地的路径
     * @throws SftpException
     * @throws FileNotFoundException
     * @throws Exception
     */
    public boolean download(String directory, String downloadFile, String saveFile) {
        boolean success = false;
        FileOutputStream fos = null;
        try {
            sftp.cd(directory);
            File file = new File(saveFile);
            System.out.println("-------------file:" + (null != file ? file : file.toString()));
            // 判断目标文件所在的目录是否存在
            if (!file.getParentFile().exists()) {
                // 如果目标文件所在的目录不存在，则创建父目录
                file.getParentFile().mkdirs();
            }
            fos = new FileOutputStream(file);
            sftp.get(downloadFile, fos);
            System.out.println("-------------文件下载成功");
            success = true;
        } catch (Exception e) {
            System.err.println(e.getMessage());
        } finally {
            if (fos != null) {
                try {
                    fos.flush();
                    fos.close();
                    fos = null;
                } catch (IOException e) {
                    System.err.println(e.getMessage());
                }
            }
        }
        return success;
    }

    /**
     * 
     * makeFile
     * 
     * @Description: 创建空文件
     * @author Administrator
     * @date 2018年1月9日 下午5:46:20
     * @param directory
     * @param uploadFile
     * @return
     * 
     */
    public boolean makeFile(String directory, String uploadFile) {
        boolean success = false;
        FileInputStream fis = null;
        try {
            sftp.cd(directory);
        } catch (SftpException e) {
            System.err.println("directory is not exist");
            try {
                sftp.mkdir(directory);
                sftp.cd(directory);
            } catch (SftpException e1) {
                System.err.println(e.getMessage());
                return false;
            }
        }
        try {
            sftp.put(uploadFile);
            success = true;
        } catch (Exception e) {
            System.err.println(e.getMessage());
        } finally {
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    System.err.println(e.getMessage());
                }
            }
        }
        return success;
    }

    @SuppressWarnings("unchecked")
    public Set<String> listFiles(String dir) throws SftpException {
        Vector<LsEntry> files = new Vector<>();
        try {
            files = sftp.ls(dir);
        } catch (Exception e) {
            return Sets.newConcurrentHashSet();
        }

        if (null != files) {
            Set<String> fileNames = Sets.newConcurrentHashSet();
            Iterator<LsEntry> iter = files.iterator();
            while (iter.hasNext()) {
                String fileName = iter.next().getFilename();
                if (StringUtils.equals(".", fileName) || StringUtils.equals("..", fileName)) {
                    continue;
                }
                fileNames.add(fileName);
            }
            return fileNames;
        }
        return null;
    }

    public static void TT(String[] args) throws Exception {
        GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
        poolConfig.setMaxTotal(10);
        poolConfig.setMinIdle(1);
        poolConfig.setTestOnBorrow(true);

        ChannelSftpPool localPool = new ChannelSftpPool(new ChannelSftpFactory("runhe", "runhe123", "192.168.111.13",
                22), poolConfig);

        ChannelSftpPool bankPool = new ChannelSftpPool(new ChannelSftpFactory("jsjs", "jsjs", "221.239.93.141", 22),
                poolConfig);
        // ChannelSftpPool bankPool = new ChannelSftpPool(new
        // ChannelSftpFactory("JinPiaoTong", "jinpiaotong",
        // "221.239.93.141", 22), poolConfig);

        while (true) {
            // 银行FTP
            ChannelSftp bankSftp = bankPool.borrowObject();
            SftpUtils bankSftpUtils = new SftpUtils(bankSftp);
            // 本地FTP
            ChannelSftp localSftp = localPool.borrowObject();
            SftpUtils localSftpUtils = new SftpUtils(localSftp);

            String yyyyMMdd = DateTime.now().toString("yyyyMMdd");
            String instId = "800025000010001";
            // /pfs/instId/CHK/yyyyMMdd
            String bankDir = "/pfs/" + instId + "/CHK/" + yyyyMMdd;
            // /渤海根目录/instId/CHK
            String localPDir = "/app/ftp/bohai/" + instId + "/CHK";
            // 银行文件列表
            Set<String> bankFiles = bankSftpUtils.listFiles(bankDir);
            // 本地文件列表
            Set<String> localFiles = localSftpUtils.listFiles(localPDir + "/" + yyyyMMdd);

            Set<String> difference = Sets.difference(bankFiles, localFiles);

            String tmpDir = "D:/tmp/";
            System.out.println("-----------");
            for (String file : difference) {
                System.out.println("file:" + file);
                bankSftpUtils.download(bankDir, file, tmpDir + file);
                localSftpUtils.upload(localPDir, yyyyMMdd, tmpDir + file);
            }
            System.out.println("-----------");

            bankPool.returnObject(bankSftp);
            localPool.returnObject(localSftp);

            Thread.sleep(10000);
        }

    }

    public ChannelSftp getSftp() {
        return sftp;
    }

}